package com.xiaoyu.base.net.interceptor;

import androidx.annotation.NonNull;
import android.text.TextUtils;

import com.xiaoyu.base.data.UserData;
import com.xiaoyu.net.util.NetUtils;
import com.xiaoyu.base.net.NetworkErrorProcessor;
import com.xiaoyu.base.net.token.TokenRefresher;

import java.io.IOException;

import in.srain.cube.request.JsonData;
import in.srain.cube.util.CLog;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;

import static com.xiaoyu.net.config.Constant.HEADER_KEY_TOKEN;

public class RefreshTokenInterceptor implements Interceptor {

    private static final String TAG = "RefreshTokenInterceptor";

    @Override
    @NonNull
    public Response intercept(@NonNull Chain chain) throws IOException {
        Request request = chain.request();

        TokenRefresher.refreshIfNecessary(request);
        TokenRefresher.waitUntilRefreshedIfNecessary(request);

        request = recreateRequestWithToken(request);
        Response response = chain.proceed(request);
        int code = getCustomCodeFromResponse(response);

        if (code == NetworkErrorProcessor.ACCESS_TOKEN_EXPIRED) {
            CLog.i(TAG, "response indicate token expired, try refresh sync");
            TokenRefresher.refresh();
            request = recreateRequestWithToken(request);
            response = chain.proceed(request);
            code = getCustomCodeFromResponse(response);
        }

        if (code == NetworkErrorProcessor.NEED_LOGIN && isTokenChanged(request)) {
            CLog.i(TAG, "response indicate need login and latest token changed, retry %s", request.url());
            request = recreateRequestWithToken(request);
            response = chain.proceed(request);
        }

        return response;
    }

    private static boolean isTokenChanged(Request request) {
        String latestAccessToken = UserData.getInstance().getTokenInfo().getAccessToken();
        String requestAccessToken = request.header(HEADER_KEY_TOKEN);
        return !TextUtils.isEmpty(latestAccessToken) && !TextUtils.equals(latestAccessToken, requestAccessToken);
    }

    private static Request recreateRequestWithToken(Request request) {
        final String accessToken = UserData.getInstance().getTokenInfo().getAccessToken();
        if (accessToken == null) {
            return request;
        }
        return request.newBuilder()
                .removeHeader(HEADER_KEY_TOKEN)
                .addHeader(HEADER_KEY_TOKEN, accessToken)
                .build();
    }

    private static int getCustomCodeFromResponse(Response response) {
        String responseString = NetUtils.readResponseString(response);
        return JsonData.create(responseString).optInt("code");
    }
}